#include "key.h"
#include "gpio.h"
#include "Mydelay.h"

/* 硬件引脚定义 */
#define KEY1_PIN    GPIO_PIN_12
#define KEY1_GPIO   GPIOB
#define KEY2_PIN    GPIO_PIN_13
#define KEY2_GPIO   GPIOB
#define KEY3_PIN    GPIO_PIN_14
#define KEY3_GPIO   GPIOB

/* 按键状态机 */
typedef struct {
    uint32_t pressStartTime;   // 按键按下时间戳
    uint32_t releaseStartTime; // 按键释放时间戳
    uint8_t isPressed;         // 按键是否已确认按下
    uint8_t isDebouncing;       // 是否在消抖中
} KeyState;

static KeyState keys[3] = {0}; // 对应KEY1/KEY2/KEY3

/* 非阻塞（NonBlocking）按键检测函数 */
uint8_t Key_GetNum(void) {
    // 遍历所有按键
    for (int i = 0; i < 3; i++) {
        GPIO_PinState pinState;
			
        // 根据索引选择按键硬件
        switch (i) {
            case 0: pinState = HAL_GPIO_ReadPin(KEY1_GPIO, KEY1_PIN); break;
            case 1: pinState = HAL_GPIO_ReadPin(KEY2_GPIO, KEY2_PIN); break;
            case 2: pinState = HAL_GPIO_ReadPin(KEY3_GPIO, KEY3_PIN); break;
            default: break;
        }

        KeyState* key = &keys[i]; //从全局数组keys中取出第i个按键的状态
				
				/******************** 按键按下逻辑 ​********************/
				
        if (pinState == GPIO_PIN_RESET) // 如果检测到按键被物理按下
				{ 
					  // 情况1：首次检测到按下，开始消抖
            if (!key->isDebouncing) {//这里有点绕，表达的意思是，没有在消抖中的状态就执行下去,主要是用来标记消抖中的状态
                key->pressStartTime = MyGetTick();// 记录按下时刻的时间戳
                key->isDebouncing = 1;	 // 标记为"消抖中"状态
            } 
						// 情况2：已经在消抖过程中，检查是否满足消抖时间
						else if (MyGetTick() - key->pressStartTime >= 20)
							{
								 // 确认按键有效按下（避免重复触发）
                if (!key->isPressed) {
                    key->isPressed = 1; // 消抖完成，标记为已按下
                    return i + 1;       // 返回按键编号1/2/3
									// 注意：这里返回后会退出Key_GetNum函数，其他按键不会在本轮循环中被检测
                }
            }
        } 
				
				/******************** 按键释放逻辑 ​********************/
				
				else 
				{ // 按键释放
            if (key->isDebouncing) {
                key->releaseStartTime = MyGetTick();
                key->isDebouncing = 0;
            }
            
            // 释放消抖（可选，防止误触发）
            if (key->isPressed && (MyGetTick() - key->releaseStartTime >= 20)) {
                key->isPressed = 0; // 重置状态
            }
        }
    }
    return 0; // 无按键按下
}


